#include "03_SocketIO.hpp"
#include <sys/socket.h>     // read
#include <errno.h>          // errno 与 EINTR
#include <stdio.h>

inline bool error_msg(const char* msg = "", int ret_flag = -1)
{
    char buff[256] = {0};
    snprintf(buff, sizeof(buff), "%s | %d | %s : %s", __FILE__, __LINE__, __FILE__, msg);
    perror(buff);
    return ret_flag;
}

namespace xy
{
SocketIO::SocketIO(int fd)
    :_fd(fd){}

int SocketIO::readn(char* buff, int total_len) const
{
    int rest_len = total_len;
    char* pbuf = buff;

    while(rest_len > 0)
    {
        // 接收缓冲区current_count大小，即最多能接受的字节数
        int ret = recv(_fd, pbuf, rest_len, 0);

        // 触发中断，则继续执行
        if(ret == -1 && errno == EINTR)    
        {
            continue;
        }
        else if(ret == 0)
        {
            return total_len - rest_len;
        }
        else
        {
            rest_len -= ret;    // 更新剩余的数字
            pbuf += ret;        // 更新字符的指针
        }
    }

    return total_len;           // 全部成功接收！
}

int SocketIO::sendn(const char* buff, int total_len)
{
    int rest_len = total_len;
    const char* pbuf = buff;

    while(rest_len)
    {
        int ret = send(_fd, pbuf, rest_len, 0);
        
        // 触发中断，则继续执行
        if(ret == -1 && errno == EINTR)    
        {
            continue;
        }
        else if(ret == 0)
        {
            return total_len - rest_len;
        }
        else
        {
            rest_len -= ret;    // 更新剩余的数字
            pbuf += ret;        // 更新字符的指针
        }
    }

    return total_len;
}

int SocketIO::read_line(char* buff, int total_len) const
{
    int rest_len = total_len - 1;  // 剩余可读取长度，预留一个字节给'\0'
    int cur_len = 0;               // 已读取的字符长度
    char* pbuf = buff;             // 当前缓冲区位置指针
    while(rest_len > 0)
    {   
        // 注意，此处传递的是指针的地址，而不是缓冲区的地址
        //int ret = recv(_fd, &pbuf, rest_len, MSG_PEEK);     // 查看数据但不取出
        int ret = recv(_fd, pbuf, rest_len, MSG_PEEK);     // 查看数据但不取出
        if(ret == -1 && errno == EINTR)
        {
            continue;
        }    
        else if(ret < 0)
        {
            return error_msg("recv rest_len");
        }
        else if(ret == 0)
        {
            return cur_len;
        }
        else{
            for(int i = 0; i < ret; ++i)
            {
                // 找了'\n', 拷贝'\n'之前的数据
                if(pbuf[i] == '\n')
                {
                    int line_mark_len = i + 1;   // 包含'\n'
                    if(readn(pbuf, line_mark_len) != line_mark_len)
                    {
                        return error_msg("recv mark_len");
                    }
                    cur_len += line_mark_len;
                    rest_len -= line_mark_len;
                    buff[cur_len] = '\0';       // 在本次读取的末尾添加结束符
                    return cur_len;
                }
            }

            // 没找到'\n', 拷贝所有的数据
            //ret = readn(pbuf, line_rest_len);
            if(readn(pbuf, ret) != ret){
                return error_msg("recv ret");
            }
            pbuf[cur_len] = '\0';
            
            // 更新指针与计数器，继续循环读取
            cur_len += ret;
            pbuf += ret;
            rest_len -= ret;
    
            // 如果缓冲区已满且仍然没有找到换行符，返回已读取内容
            if(rest_len == 0)
            {
                buff[cur_len] = '\0';
                return cur_len;
            }
        }
    }

    // 缓冲区已满
    buff[cur_len] = '\0';
    return cur_len;
}

int SocketIO::recv_peek()
{
    char buff[20] = {0};
    int ret = 0;
    
    do{
       ret = recv(_fd, buff, sizeof(buff), MSG_PEEK);     
    }while(ret == -1 && errno == EINTR);

    if(ret < 0)
    {
        error_msg("peek");
    }
    return ret;
}

}
